package org.doubango.networkdemo

import android.Manifest
import android.content.pm.PackageManager
import android.net.ConnectivityManager
import android.net.NetworkCapabilities
import android.net.NetworkRequest
import android.net.wifi.WifiManager
import android.os.Build
import android.os.Bundle
import android.os.PowerManager
import android.telephony.TelephonyManager
import android.widget.Toast
import androidx.activity.enableEdgeToEdge
import androidx.annotation.RequiresPermission
import androidx.appcompat.app.AppCompatActivity
import androidx.core.content.ContextCompat
import androidx.core.view.ViewCompat
import androidx.core.view.WindowInsetsCompat
import org.doubango.networkdemo.databinding.ActivityMainBinding
import timber.log.Timber
import java.net.InetAddress
import java.nio.ByteBuffer

class MainActivity : AppCompatActivity() {

    private val binding by lazy { ActivityMainBinding.inflate(layoutInflater) }
    private val connectivityManager: ConnectivityManager by lazy { getSystemService(CONNECTIVITY_SERVICE) as ConnectivityManager }
    private var wifiLock: WifiManager.WifiLock? = null
    private var cellularLock: PowerManager.WakeLock? = null

    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        enableEdgeToEdge()
        setContentView(binding.root)
        ViewCompat.setOnApplyWindowInsetsListener(findViewById(R.id.main)) { v, insets ->
            val systemBars = insets.getInsets(WindowInsetsCompat.Type.systemBars())
            v.setPadding(systemBars.left, systemBars.top, systemBars.right, systemBars.bottom)
            insets
        }
        initListeners()
        Timber.i("onCreate")
    }

    private fun initListeners() {
        binding.registerButton.setOnClickListener { registerNetworkChangedCallback() }
        binding.unregisterButton.setOnClickListener { unregisterNetworkChangedCallback() }
        binding.printNetInterfaces.setOnClickListener { NetUtil.getIp() }
        binding.isMobileDataEnableButton.setOnClickListener {
            isMobileEnabled()
        }
        binding.getWifiDns.setOnClickListener { printWifiDns() }
    }

    @RequiresPermission(Manifest.permission.ACCESS_WIFI_STATE)
    private fun printWifiDns() {
        val wifiManager = application.getSystemService(WIFI_SERVICE) as WifiManager
        wifiManager.dhcpInfo?.let { dhcpInfo ->
            val dns1 = intIpToStringIp(dhcpInfo.dns1)
            val dns2 = intIpToStringIp(dhcpInfo.dns2)
            Timber.i("dns1=$dns1, dns2=$dns2")
        }
    }

    private fun intIpToStringIp(intIp: Int) = InetAddress.getByAddress(ByteBuffer.allocate(4).putInt(intIp).array().reversedArray()).hostAddress

    private fun isMobileEnabled() {
        val telephonyManager = application.getSystemService(TELEPHONY_SERVICE) as TelephonyManager
        if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
            // Android 8.0可以使用下面的方法判断是否打开移动数据开关，而无需要反射调用ConnectivityManager中的方法。
            if (ContextCompat.checkSelfPermission(this, Manifest.permission.ACCESS_NETWORK_STATE) == PackageManager.PERMISSION_GRANTED) {
                val isDataEnabled = telephonyManager.isDataEnabled
                toast("Android 8.0+,isDataEnabled=$isDataEnabled")
            }
        } else {
            // Android 8.0以下TelephonyManager还没有isDataEnabled()，只有getDataEnabled()，但是这个方法是隐藏的
            // 还有ConnectivityManager.getMobileDataEnabled()也是隐藏函数，它内部是调用TelephonyManager.getDataEnabled()
            val method = TelephonyManager::class.java.getDeclaredMethod("getDataEnabled").apply { isAccessible = true }
            val isDataEnabled = method.invoke(telephonyManager)
            toast("Android 8.0以下,isDataEnabled=$isDataEnabled")
        }
    }

    private fun toast(msg: String) = Toast.makeText(this, msg, Toast.LENGTH_SHORT).show()

    private fun registerNetworkChangedCallback() {
        if (!isRegisterReceiver) {
            if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.N) {
                // 如果Android版本等于7.0(API 24)或以上
                connectivityManager.registerDefaultNetworkCallback(mNetworkCallback)
            } else {
                val networkRequest = NetworkRequest.Builder().build()
                connectivityManager.registerNetworkCallback(networkRequest, mNetworkCallback)
            }
            isRegisterReceiver = true
        }
    }

    private fun unregisterNetworkChangedCallback() {
        if (isRegisterReceiver) {
            connectivityManager.unregisterNetworkCallback(mNetworkCallback)
            isRegisterReceiver = false
        }
    }

    private fun acquire(isWifi: Boolean) {
        if (isWifi && wifiLock == null) {
            val wifiManager = application.getSystemService(WIFI_SERVICE) as WifiManager
            wifiLock = wifiManager.createWifiLock(WifiManager.WIFI_MODE_FULL_HIGH_PERF, "${packageName}.LockWifi")?.also {
                if (!it.isHeld) {
                    it.acquire()
                    Timber.i("已申请Wi-Fi锁：${it.isHeld}")
                }
            }
            Timber.i("wifiLock = $wifiLock")
        } else if (!isWifi && cellularLock == null) {
            val powerManager = application.getSystemService(POWER_SERVICE) as PowerManager
            cellularLock = powerManager.newWakeLock(PowerManager.PARTIAL_WAKE_LOCK, "${packageName}.LockCellular")?.also {
                if (!it.isHeld) {
                    it.acquire()
                    Timber.i("已申请蜂窝锁：${it.isHeld}")
                }
            }
        }
    }

    fun releaseWakeLock() {
        wifiLock?.let {
            if (it.isHeld) {
                it.release()
                Timber.i("wifiLock已释放")
            }
            wifiLock = null
        }
        cellularLock?.let {
            if (it.isHeld) {
                it.release()
                Timber.i("cellularLock已释放")
            }
            cellularLock = null
        }
    }

    private var isRegisterReceiver = false

    override fun onDestroy() {
        super.onDestroy()
        unregisterNetworkChangedCallback()
        releaseWakeLock()
        Timber.i("onDestroy")
    }

    override fun onResume() {
        super.onResume()
        Timber.i("onResume")
    }

    override fun onPause() {
        super.onPause()
        Timber.i("onPause")
    }

    override fun onStop() {
        super.onStop()
        Timber.i("onStop")
    }

    private fun hasNetwork(networkCapabilities: NetworkCapabilities) {
        Timber.i("有网络")
        val isWifi = networkCapabilities.hasTransport(NetworkCapabilities.TRANSPORT_WIFI)
        val isCellular = networkCapabilities.hasTransport(NetworkCapabilities.TRANSPORT_CELLULAR)
        if (isWifi || isCellular) {
            acquire(isWifi)
        }
    }

    private fun noNetwork() {
        Timber.i("无网络")
    }

    private fun hasIp(ip: String) {
        toast("当前网络IP：$ip")
    }

    private val mNetworkCallback = NetworkCallbackImpl(::hasNetwork, ::noNetwork, ::hasIp)

}